import * as vscode from 'vscode';
import { spawn, ChildProcess } from 'child_process';
import { logger } from '../logger';
import { parseHdcOutput } from '../utils/hdcUtils';

// 定义日志级别枚举
export enum LogLevel {
    DEBUG = 'Debug',
    INFO = 'Info',
    WARN = 'Warn',
    ERROR = 'Error',
    FATAL = 'Fatal',
    ALL = 'All'  // 用于表示所有级别
}

export class HiLogService {
    private static instance: HiLogService;
    private logProcess: ChildProcess | null = null;
    private deviceCheckInterval: NodeJS.Timeout | null = null;
    private onLogUpdateCallbacks: ((log: string) => void)[] = [];
    private onDeviceDisconnectedCallbacks: (() => void)[] = [];
    private deviceConnected: boolean = false;
    private isRunning: boolean = false;
    private logBuffer: string[] = [];
    private maxBufferSize: number = 1000; // 保留最近1000行日志
    private currentLogLevel: LogLevel = LogLevel.INFO; // 默认日志级别为 INFO
    private targetDevice: string = ''; // 目标设备ID
    private processFilter: string = ''; // 进程过滤器
    private searchKeyword: string = ''; // 搜索关键词
    private saveLogs: boolean = false; // 是否保存日志

    private constructor() {
        // Private constructor to enforce singleton pattern
    }

    public static getInstance(): HiLogService {
        if (!HiLogService.instance) {
            HiLogService.instance = new HiLogService();
        }
        return HiLogService.instance;
    }

    // 设置日志级别
    public setLogLevel(level: LogLevel): void {
        if (this.currentLogLevel === level) {
            return; // 如果级别相同则不做任何改变
        }
        
        this.currentLogLevel = level;
        logger.info(`HiLog level changed to: ${level}`);
        
        // 如果当前正在运行日志流，则重启以应用新的日志级别
        if (this.isRunning && this.deviceConnected) {
            this.stopLogStream();
            this.startLogStream();
        }
    }

    // 获取当前日志级别
    public getLogLevel(): LogLevel {
        return this.currentLogLevel;
    }

    // 注册日志更新回调
    public onLogUpdate(callback: (log: string) => void): vscode.Disposable {
        this.onLogUpdateCallbacks.push(callback);
        // 如果已经有日志，立即调用回调发送缓存的日志
        if (this.logBuffer.length > 0) {
            callback(this.logBuffer.join('\n'));
        }

        return {
            dispose: () => {
                const index = this.onLogUpdateCallbacks.indexOf(callback);
                if (index !== -1) {
                    this.onLogUpdateCallbacks.splice(index, 1);
                }
            }
        };
    }

    // 注册设备断开连接回调
    public onDeviceDisconnected(callback: () => void): vscode.Disposable {
        this.onDeviceDisconnectedCallbacks.push(callback);

        return {
            dispose: () => {
                const index = this.onDeviceDisconnectedCallbacks.indexOf(callback);
                if (index !== -1) {
                    this.onDeviceDisconnectedCallbacks.splice(index, 1);
                }
            }
        };
    }

    // 检查设备是否连接
    public async checkDeviceConnection(): Promise<boolean> {
        return new Promise((resolve) => {
            // Use hdc list targets command to get real device information
		const { exec } = require('child_process');
		// 使用bash作为shell执行命令，但不使用交互式模式
		exec(`hdc list targets`, {
		}, (error: any, stdout: string, stderr: string) => {
			if (error) {
				console.error(`Error executing hdc command: ${error.message}`);
				return;
			}

			if (stderr) {
				console.warn(`hdc command warning: ${stderr}`);
			}

			// Parse the output of hdc list targets
			const devices = parseHdcOutput(stdout);
			
			if (devices.length === 0) {
				console.log("No devices found, hdc output was:", stdout);
                resolve(false);
            } else {
                resolve(true);
            }
        });
    })}



    // 开始监控设备连接状态
    public startDeviceMonitoring(): void {
        if (this.deviceCheckInterval) {
            clearInterval(this.deviceCheckInterval);
        }

        // 立即检查一次设备连接状态
        this.checkDeviceConnection().then(connected => {
            if (connected && !this.deviceConnected) {
                this.deviceConnected = true;
                // 如果没有指定目标设备，则获取当前设备列表并设置第一个设备为目标
                if (!this.targetDevice) {
                    this.getConnectedDevices().then(devices => {
                        if (devices.length > 0) {
                            this.targetDevice = devices[0];
                            logger.info(`Automatically set target device to: ${this.targetDevice}`);
                        }
                        this.startLogStream();
                    });
                } else {
                    this.startLogStream();
                }
                vscode.window.showInformationMessage('设备已连接，HiLog 日志流已启动');
            } else if (!connected && this.deviceConnected) {
                this.deviceConnected = false;
                this.stopLogStream();
                // 清除目标设备设置
                this.targetDevice = '';
                vscode.window.showInformationMessage('设备已断开连接，HiLog 日志流已停止');
                
                // 通知所有订阅者设备已断开连接
                this.onDeviceDisconnectedCallbacks.forEach(callback => {
                    callback();
                });
            }
        });

        // 每2秒检查一次设备连接状态
        this.deviceCheckInterval = setInterval(async () => {
            const connected = await this.checkDeviceConnection();
            
            if (connected && !this.deviceConnected) {
                this.deviceConnected = true;
                // 如果没有指定目标设备，则获取当前设备列表并设置第一个设备为目标
                if (!this.targetDevice) {
                    this.getConnectedDevices().then(devices => {
                        if (devices.length > 0) {
                            this.targetDevice = devices[0];
                            logger.info(`Automatically set target device to: ${this.targetDevice}`);
                        }
                        this.startLogStream();
                    });
                } else {
                    this.startLogStream();
                }
                vscode.window.showInformationMessage('设备已连接，HiLog 日志流已启动');
            } else if (!connected && this.deviceConnected) {
                this.deviceConnected = false;
                this.stopLogStream();
                // 清除目标设备设置
                this.targetDevice = '';
                vscode.window.showInformationMessage('设备已断开连接，HiLog 日志流已停止');
                
                // 通知所有订阅者设备已断开连接
                this.onDeviceDisconnectedCallbacks.forEach(callback => {
                    callback();
                });
            }
        }, 2000);
    }

    // 停止监控设备连接状态
    public stopDeviceMonitoring(): void {
        if (this.deviceCheckInterval) {
            clearInterval(this.deviceCheckInterval);
            this.deviceCheckInterval = null;
        }
        this.stopLogStream();
    }

    // 开始日志流
    private startLogStream(): void {
        if (this.isRunning) {
            return;
        }

        this.isRunning = true;
        logger.info(`Starting HiLog stream with level: ${this.currentLogLevel}...`);

        try {
            // 根据日志级别和过滤器构建命令
            let args: string[];
            
            // 如果指定了目标设备，添加 -t 参数
            if (this.targetDevice) {
                args = ['-t', this.targetDevice, 'hilog'];
                logger.info(`Using target device: ${this.targetDevice}`);
            } else {
                // 没有指定目标设备，抛出异常
                throw new Error('No target device specified');
            }
            
            // 添加日志级别过滤
            if (this.currentLogLevel && this.currentLogLevel !== LogLevel.ALL) {
                // 将日志级别转换为hilog参数简写形式
                let levelParam: string;
                switch (this.currentLogLevel) {
                    case LogLevel.DEBUG:
                        levelParam = 'D';
                        break;
                    case LogLevel.INFO:
                        levelParam = 'I';
                        break;
                    case LogLevel.WARN:
                        levelParam = 'W';
                        break;
                    case LogLevel.ERROR:
                        levelParam = 'E';
                        break;
                    case LogLevel.FATAL:
                        levelParam = 'F';
                        break;
                    default:
                        levelParam = 'I'; // 默认INFO级别
                }
                args.push('-L', levelParam);
            } else if (this.currentLogLevel === LogLevel.ALL) {
                // Do nothing
            }
            
            // 添加进程过滤
            // if (this.processFilter && this.processFilter !== '全部进程') {
            //     args.push('-p', this.processFilter);
            // }
            
            // 添加搜索关键词过滤
            // if (this.searchKeyword) {
            //     args.push('|', 'grep', this.searchKeyword);
            // }
            
            logger.info(`Running command: hdc ${args.join(' ')}`);
            this.logProcess = spawn('hdc', args);

            this.logProcess.stdout?.on('data', (data) => {
                const logs = data.toString();
                this.addToLogBuffer(logs);
                console.log(logs);

                // 通知所有订阅者
                this.onLogUpdateCallbacks.forEach(callback => {
                    callback(logs);
                });
            });

            this.logProcess.stderr?.on('data', (data) => {
                logger.error(`HiLog stderr: ${data.toString()}`);
            });

            this.logProcess.on('close', (code) => {
                logger.info(`HiLog process exited with code ${code}`);
                this.isRunning = false;
                this.logProcess = null;
            });

            this.logProcess.on('error', (err) => {
                logger.error(`Failed to start HiLog process: ${err.message}`);
                this.isRunning = false;
                this.logProcess = null;
            });
        } catch (error) {
            logger.error(`Error starting HiLog process: ${error instanceof Error ? error.message : 'Unknown error'}`);
            this.isRunning = false;
        }
    }

    // 停止日志流
    private stopLogStream(): void {
        if (this.logProcess) {
            this.logProcess.kill();
            this.logProcess = null;
        }
        this.isRunning = false;
        logger.info('HiLog stream stopped');
    }

    // 添加日志到缓冲区
    private addToLogBuffer(logs: string): void {
        const logLines = logs.split('\n').filter(line => line.trim());
        
        // 添加新日志行到缓冲区
        this.logBuffer = [...this.logBuffer, ...logLines];
        
        // 如果超出最大缓冲区大小，则移除最旧的日志
        if (this.logBuffer.length > this.maxBufferSize) {
            this.logBuffer = this.logBuffer.slice(this.logBuffer.length - this.maxBufferSize);
        }
    }

    // 清除日志缓冲区
    public clearLogBuffer(): void {
        this.logBuffer = [];
    }

    // 获取当前的日志缓冲区
    public getLogBuffer(): string[] {
        return [...this.logBuffer];
    }

    // 获取连接的设备列表
    public async getConnectedDevices(): Promise<string[]> {
        return new Promise((resolve) => {
            const { exec } = require('child_process');
            // 使用hdc命令获取设备列表
            exec(`hdc list targets`, {}, (error: any, stdout: string, stderr: string) => {
                if (error) {
                    console.error(`Error executing hdc command: ${error.message}`);
                    resolve([]);
                    return;
                }

                if (stderr) {
                    console.warn(`hdc command warning: ${stderr}`);
                }

                // 解析hdc输出获取设备列表
                const devices = parseHdcOutput(stdout);
                // 只返回设备ID数组
                resolve(devices.map(device => device.id));
            });
        });
    }

    // 设置目标设备
    public setTargetDevice(deviceId: string): void {
        this.targetDevice = deviceId;
        this.deviceConnected = true;
        logger.info(`Target device set to: ${deviceId}`);
    }

    // 设置进程过滤器
    public setProcessFilter(process: string): void {
        this.processFilter = process;
        logger.info(`Process filter set to: ${process}`);
    }

    // 设置搜索关键词
    public setSearchKeyword(keyword: string): void {
        this.searchKeyword = keyword;
        logger.info(`Search keyword set to: ${keyword}`);
    }

    // 重启日志监控
    public restartLogMonitoring(): void {
        if (this.isRunning) {
            this.stopLogStream();
        }
        if (this.deviceConnected) {
            this.startLogStream();
        }
    }

    // 启用或禁用日志保存
    public enableLogSaving(enable: boolean): void {
        this.saveLogs = enable;
        logger.info(`Log saving ${enable ? 'enabled' : 'disabled'}`);
    }
}
